# ハッシュの監視
package MonHash;

sub TIEHASH {
    my ($pkg, $name, $rh) = @_;
    my $obj = {
	name => $name, hash => {%$rh},
    };
    bless $obj, $pkg;
    $obj;
}

sub FETCH {
    my ($obj, $index) = @_;
    my $value = $obj->{'hash'}->{$index};
    print 'Read : $', $obj->{'name'}, "{$index} -> $value\n";
    $value;
}

sub STORE {
    my ($obj, $index, $new_value) = @_;
    print 'Write : $', $obj->{'name'}, "{$index} <- $new_value\n";
    $obj->{'hash'}->{$index} = $new_value;
}

sub CLEAR {
    my $obj = shift;
    print 'Clear : %', "$obj->{'name'}\n";
    $obj->{'hash'} = {};
}

sub DESTROY {
    my $obj = shift;
    if( $obj->{'name'} ne '__UNMONITOR__' ){
	print 'DESTORY %', "$obj->{'name'}\n";
    }
}

sub unmonitor {
    my ($pkg, $rvar) = @_;
    my $last_hash;
    {
	my $obj = tied %$rvar;
	$last_hash = $obj->{'hash'};
	$obj->{'name'} = '__UNMONITOR__'
    }
    untie %$rvar;
    %$rvar = %$last_hash;
}

package main;

%h = (a => 10, b => 20, c => 30);

print %h, "\n";

tie %h, 'MonHash', 'h', \%h;

$x = $h{'b'};
print "x = $x\n";

$h{'b'} = 200;

$y = $h{'b'};
print "y = $y\n";

%h = ( a => 100, b => 200, c => 300 );

MonHash->unmonitor( \%h );

print %h;

# end of file
